﻿using System;
using System.Collections.Generic;
using System.Text;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;

namespace Daybreak.Core.Input
{
    /// <summary>
    /// Event driven mouse device
    /// </summary>
    public sealed class MouseDevice
    {
        public event MouseButtonHandler MouseDown;
        public event MouseButtonHandler MouseUp;
        public event MouseWheelHandler MouseWheel;
        public event MouseMoveHandler MouseMove;

        public TimeSpanWatcher TimeStep;

        private MouseState lastState;
        private Point position;

        public MouseDevice(float updatePerSecond)
        {
            lastState = new MouseState();
            TimeStep = new TimeSpanWatcher(updatePerSecond);

        }

        /// <summary>
        /// Updates the current mouse State and triggers events if necessary.
        /// </summary>
        /// <param name="elapsedTime"></param>
        public void Update(float elapsedTime)
        {
            float delta = TimeStep.GetNextDelta(elapsedTime);

            if (delta == 0)
                return;

            MouseState curState = Mouse.GetState();

            // Check for mouse move event
            if ((curState.X != lastState.X) || (curState.Y != lastState.Y))
            {
                position = new Point(curState.X, curState.Y);

                if (MouseMove != null)
                {
                    MouseMove(this, curState, curState.X - lastState.X, curState.Y - lastState.Y);
                }
            }


            ProcessButton(curState, curState.LeftButton, lastState.LeftButton, MouseButtons.Left);
            ProcessButton(curState, curState.RightButton, lastState.RightButton, MouseButtons.Right);

            int wheelDelta = curState.ScrollWheelValue - lastState.ScrollWheelValue;

            if (wheelDelta != 0 && MouseWheel != null)
                MouseWheel(this, curState, wheelDelta);

            // Update mouse state
            lastState = curState;


        }

        private void ProcessButton(MouseState mouseState, ButtonState btnCur, ButtonState btnLast, MouseButtons btn)
        {
            if (btnCur != btnLast)
            {
                if ((MouseUp != null) || (MouseDown != null))
                {
                    if (btnCur == ButtonState.Released)
                    {
                        if (MouseUp != null)
                            MouseUp(this, mouseState, btn);
                    }
                    else
                    {
                        if (MouseDown != null)
                        {
                            MouseDown(this, mouseState, btn);
                        }
                    }
                }
            }

        }

        /// <summary>
        /// Retrieves the current mouse position.
        /// </summary>
        public Point Position
        {
            get { return position; }
        }

    }

    /// <summary>
    /// <para>Specifies constants that define which mouse button was pressed.</para>
    /// </summary>
    [Flags]
    public enum MouseButtons
    {
        /// <summary>
        /// <para>No mouse button was pressed.</para>
        /// </summary>
        None = 0,

        /// <summary>
        /// <para>The left mouse button was pressed.</para>
        /// </summary>
        Left = 0x100000,

        /// <summary>
        /// <para>The right mouse button was pressed.</para>
        /// </summary>
        Right = 0x200000,

        /// <summary>
        /// <para>The middle mouse button was pressed.</para>
        /// </summary>
        //Middle = 0x400000,

        /// <summary>
        /// <para>The first XButton was pressed.</para>
        /// </summary>
        //XButton1 = 0x800000,

        /// <summary>
        /// <para>The second XButton was pressed.</para>
        /// </summary>
        //XButton2 = 0x1000000
    }

    public delegate void MouseMoveHandler(MouseDevice sender, MouseState state, int deltaX, int deltaY);
    public delegate void MouseButtonHandler(MouseDevice sender, MouseState state, MouseButtons buttons);
    public delegate void MouseWheelHandler(MouseDevice sender, MouseState state, int wheelDelta);

}
